<script setup lang="ts">
import { ref } from "vue";
import { provide } from "vue";
import { showToast } from "vant";
import useRouterHook from "@/hooks/useRouterHook";
import { APPROVE_TYPE_DETAIL_API_MAP } from "./constants";
import usePost from "@/hooks/usePost";
import { ProcessTypeEnum, TabEnum } from "../approveList/constants";
import { useAppStore } from "@/store";
import ApproveDetail from "@/components/ApproveDetail/index.vue";

// 通过
const { runAsync: approveCallBackApi, loading: approveCallBackLoading } = usePost("POST", "/bpm-api/task/handle");
// 退回
const { runAsync: approveSendBackApi, loading: approveSendBackLoading } = usePost("GET", "/bpm-api/process/stopProcessInstance");

const appStore = useAppStore();
const currentUserId = appStore.getUserId();

const { route } = useRouterHook();
const { menu, id, type } = route.query;
const req = APPROVE_TYPE_DETAIL_API_MAP[+(type ?? 0) as ProcessTypeEnum];
/** 查询详情接口 */
const { runAsync: getDetailApi } = usePost(req.methods, req.url);

const cancelDialogShow = ref(false),
	/** 退回原因 */
	reason = ref(""),
	approvePopupShow = ref(false),
	detail = ref<any>(),
	approveRef = ref();

/** 点击下方按钮
 * @param flag 0:拒绝 1:同意
 */
const handleApproval = async (flag: 0 | 1) => {
	if (flag) {
		// 同意
		await confirmApproval(1);
	} else {
		cancelDialogShow.value = true;
	}
};

/** 同意或退回api
 * @param flag 0:退回 1:同意
 */
const confirmApproval = async (flag: 0 | 1) => {
	try {
		const api = flag ? approveCallBackApi : approveSendBackApi;
		await api({
			taskId: detail.value.taskId,
			currentUserId,
			comment: flag ? undefined : reason.value
		});
		showToast({
			message: `已${flag ? "同意" : "退回"}`
		});
		await getDetail();
		await approveRef.value?.getApprovalHistory();
	} catch (error: any) {
		console.log("error", error);
		showToast({
			message: error.message || `操作失败，请重试`
		});
	}
};

/** 打开审批弹窗 */
const viewApproveDetail = () => {
	approvePopupShow.value = true;
};

/** 关闭前回调 */
const beforeClose = (action: string) => {
	if (action === "confirm") {
		if (!reason.value) {
			showToast({
				message: `请输入退回原因`
			});
			return false;
		}
		return confirmReturn();
	} else {
		return true;
	}
};

/** 确认退回 */
const confirmReturn = async () => {
	await confirmApproval(0);
	cancelDialogShow.value = false;
	reason.value = "";
	return true;
};

/** 获取详情 */
const getDetail = async () => {
	const { data } = await getDetailApi({
		id
	});
	detail.value = data;
};

const init = async () => {
	if (id) {
		await getDetail();
	} else {
		showToast({
			message: `参数缺失`
		});
	}
};
init();

provide("detail", detail);
</script>

<template>
	<div class="approve-detail">
		<div class="detail-map" v-if="detail?.id && req">
			<component :is="req.component"></component>
		</div>

		<div class="fix_bottom">
			<div class="approval_button">
				<div class="left_button">
					<div v-if="detail?.flowId" class="mini_button" @click="viewApproveDetail">
						<van-icon name="cluster-o" />
						<span>审批详情</span>
					</div>
				</div>
				<div class="right_button" v-if="+(menu ?? TabEnum.COMPLETED) === TabEnum.PENDING && detail?.taskId">
					<van-button type="danger" class="button" @click="handleApproval(0)">退回</van-button>
					<van-button color="#1E8FA0" class="button" @click="handleApproval(1)">同意</van-button>
				</div>
			</div>
		</div>

		<van-overlay :show="approveCallBackLoading || approveSendBackLoading" class-name="define_loading">
			<van-loading color="#1e8fa0" />
		</van-overlay>

		<!-- 流程详情弹窗 -->
		<ApproveDetail v-if="detail?.id" v-model="approvePopupShow" ref="approveRef" :procInstId="detail.flowId"></ApproveDetail>
		<!-- 点击退回打开弹窗，输入退回原因 -->
		<van-dialog
			v-model:show="cancelDialogShow"
			title="退回原因"
			show-cancel-button
			confirm-button-color="#1E8FA0"
			:beforeClose="beforeClose"
		>
			<van-field
				v-model="reason"
				:autosize="{
					minHeight: 60
				}"
				type="textarea"
				label="退回原因："
				placeholder="请输入退回原因"
				maxlength="100"
				required
				clearable
				show-word-limit
				border
			/>
		</van-dialog>
	</div>
</template>

<style scoped lang="less">
// 按钮高度
@button_height: 40px;
// 按钮上下padding
@button_padding: 15px;

.approve-detail {
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
	background-color: #fafafa;
	max-width: 420px;
	min-height: 100%;
	padding-bottom: calc(@button_height + (@button_padding * 2) + constant(safe-area-inset-bottom));
	padding-bottom: calc(@button_height + (@button_padding * 2) + env(safe-area-inset-bottom));
	p {
		margin: 0;
	}
}

.fix_bottom {
	width: 100%;
	position: fixed;
	bottom: 0;
	left: 50%;
	transform: translateX(-50%);
	border-top: 1px solid #eeeeee;
	background-color: #fff;
	max-width: 420px;
	padding: @button_padding;
	box-sizing: border-box;
	padding-bottom: calc(@button_padding + constant(safe-area-inset-bottom));
	padding-bottom: calc(@button_padding + env(safe-area-inset-bottom));
	.approval_button {
		height: @button_height;
		width: 100%;
		display: flex;
		justify-content: space-between;
		.left_button {
			display: flex;
			justify-content: flex-start;
			align-items: center;
			flex-shrink: 0;
			.mini_button {
				height: 100%;
				display: flex;
				flex-direction: column;
				justify-content: center;
				align-items: center;
				span {
					font-size: 12px;
					margin-top: 3px;
				}
				.van-icon {
					font-size: 22px;
				}
				&:active {
					background-color: #f6f6f6;
				}
			}
		}
		.right_button {
			flex-grow: 1;
			display: flex;
			justify-content: flex-end;
			.button {
				width: 40%;
				height: 100%;
				margin-right: 10px;
				&:last-child {
					margin-right: 0;
				}
			}
		}
	}
}

.define_loading {
	background-color: rgba(255, 255, 255, 0.7);
	display: flex;
	justify-content: center;
	align-items: center;
}
</style>
